from flask import Flask, render_template, request, jsonify, send_file, redirect, url_for, flash, session
import os
from werkzeug.utils import secure_filename
from modules.pdf_extractor import extract_words
from modules.pdf_to_audio import convert_to_audio
import io
from modules.user_model import db, User, Word
from flask_login import LoginManager, login_user, logout_user, login_required, current_user

app = Flask(__name__, static_url_path='/essay_helper/static')
app.config['UPLOAD_FOLDER'] = 'uploads/'
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 16MB max upload
app.config['ALLOWED_EXTENSIONS'] = {'pdf'}
app.config['SECRET_KEY'] = 'your-secret-key-here'  # 用于会话安全
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///essay_helper.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['APPLICATION_ROOT'] = '/essay_helper'  # 设置应用根路径

# 确保上传目录存在
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
os.makedirs('audio_files', exist_ok=True)  # 确保音频文件目录存在

# 初始化数据库
db.init_app(app)

# 初始化登录管理器
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']

# 初始化数据库表
@app.before_first_request
def create_tables():
    db.create_all()

# 自定义URL生成，添加前缀
def get_prefix():
    return '/essay_helper'

# 更新url_for，添加前缀
@app.context_processor
def override_url_for():
    def prefixed_url_for(endpoint, **values):
        if endpoint == 'static':
            # 静态文件URL已经在Flask初始化时设置了前缀
            return url_for(endpoint, **values)
        url = url_for(endpoint, **values)
        return get_prefix() + url
    return dict(url_for=prefixed_url_for)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form.get('username')
        email = request.form.get('email')
        password = request.form.get('password')
        
        # 验证用户信息
        if not username or not email or not password:
            flash('所有字段都是必填的', 'error')
            return redirect(url_for('register'))
        
        # 检查用户名或邮箱是否已存在
        if User.query.filter_by(username=username).first():
            flash('用户名已被使用', 'error')
            return redirect(url_for('register'))
        
        if User.query.filter_by(email=email).first():
            flash('邮箱已被注册', 'error')
            return redirect(url_for('register'))
        
        # 创建新用户
        user = User(username=username, email=email)
        user.set_password(password)
        db.session.add(user)
        db.session.commit()
        
        flash('注册成功，请登录', 'success')
        return redirect(url_for('login'))
    
    return render_template('register.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        
        # 验证用户存在并且密码正确
        user = User.query.filter_by(username=username).first()
        if user and user.check_password(password):
            login_user(user)
            next_page = request.args.get('next')
            flash('登录成功', 'success')
            return redirect(next_page or url_for('dashboard'))
        
        flash('用户名或密码错误', 'error')
    
    return render_template('login.html')

@app.route('/logout')
@login_required
def logout():
    logout_user()
    flash('您已成功登出', 'success')
    return redirect(url_for('login'))

@app.route('/dashboard')
@login_required
def dashboard():
    # 获取用户词汇表
    vocabulary = current_user.get_vocabulary()
    return render_template('dashboard.html', 
                          vocabulary=vocabulary, 
                          vocabulary_count=len(vocabulary))

@app.route('/extract_words', methods=['POST'])
@login_required
def extract_unfamiliar_words():
    if 'file' not in request.files:
        return jsonify({'error': '未找到文件'}), 400
    
    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': '未选择文件'}), 400
    
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        file.save(filepath)
        
        try:
            # 获取用户已有词汇表
            user_vocab = set(current_user.get_vocabulary())
            
            # 提取不在用户生词本中的单词
            words = extract_words(filepath, user_vocab)
            
            # 创建响应数据
            results = {
                'words': words,
                'count': len(words)
            }
            
            return jsonify(results)
        except Exception as e:
            return jsonify({'error': str(e)}), 500
    else:
        return jsonify({'error': '不支持的文件类型'}), 400

@app.route('/add_to_vocabulary', methods=['POST'])
@login_required
def add_to_vocabulary():
    data = request.json
    words = data.get('words', [])
    
    if not words:
        return jsonify({'error': '未提供单词'}), 400
    
    try:
        # 将单词添加到用户词汇表
        for word in words:
            current_user.add_word_to_vocab(word)
        
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': f'成功添加 {len(words)} 个单词到您的生词本',
            'vocabulary_count': len(current_user.vocabulary)
        })
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500

@app.route('/download_vocabulary')
@login_required
def download_vocabulary():
    try:
        # 获取用户词汇表
        vocabulary = current_user.get_vocabulary()
        
        if not vocabulary:
            flash('您的生词本为空', 'info')
            return redirect(url_for('dashboard'))
        
        # 创建内存中的文本文件
        file_content = '\n'.join(vocabulary)
        buffer = io.BytesIO(file_content.encode())
        buffer.seek(0)
        
        # 发送文件以供下载
        return send_file(
            buffer,
            as_attachment=True,
            download_name=f'{current_user.username}_vocabulary.txt',
            mimetype='text/plain'
        )
    except Exception as e:
        flash(f'下载失败: {str(e)}', 'error')
        return redirect(url_for('dashboard'))

@app.route('/download_words', methods=['POST'])
@login_required
def download_words():
    try:
        words = request.json.get('words', [])
        if not words:
            return jsonify({'error': '未提供单词'}), 400
            
        # 创建内存中的文本文件
        file_content = '\n'.join(words)
        buffer = io.BytesIO(file_content.encode())
        buffer.seek(0)
        
        # 发送文件以供下载
        return send_file(
            buffer,
            as_attachment=True,
            download_name='unfamiliar_words.txt',
            mimetype='text/plain'
        )
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/convert_to_audio', methods=['POST'])
@login_required
def pdf_to_audio():
    if 'file' not in request.files:
        return jsonify({'error': '未找到文件'}), 400
    
    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': '未选择文件'}), 400
    
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        file.save(filepath)
        
        try:
            # 返回多个音频文件列表而不是单个文件路径
            audio_files = convert_to_audio(filepath)
            
            # 格式化用于前端显示的数据
            audio_files_data = []
            for audio in audio_files:
                audio_files_data.append({
                    'file': audio['file'],
                    'audio_url': f'/essay_helper/download_audio/{audio["file"]}',
                    'first_word': audio['first_word'],
                    'last_word': audio['last_word'],
                    'duration': round(audio['duration'])  # 四舍五入到整数
                })
            
            return jsonify({
                'success': True,
                'message': f'已生成 {len(audio_files)} 个音频文件',
                'audio_files': audio_files_data
            })
        except Exception as e:
            return jsonify({'error': str(e)}), 500
    else:
        return jsonify({'error': '不支持的文件类型'}), 400

@app.route('/list_audio_files')
@login_required
def list_audio_files():
    """获取所有可用的音频文件列表"""
    from modules.pdf_to_audio import get_audio_files
    
    try:
        audio_files = get_audio_files()
        
        # 格式化用于前端显示的数据
        audio_files_data = []
        for audio in audio_files:
            audio_files_data.append({
                'file': audio['file'],
                'audio_url': f'/essay_helper/download_audio/{audio["file"]}',
                'first_word': audio['first_word'],
                'last_word': audio['last_word'],
                'size': audio['size']
            })
        
        return jsonify({
            'success': True,
            'audio_files': audio_files_data
        })
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/download_audio/<filename>')
@login_required
def download_audio(filename):
    return send_file(os.path.join('audio_files', filename), as_attachment=True)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=9010, debug=True) 